using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using IQIGame.Onigao.GamePlay;
using System.Collections.Generic;

namespace IQIGame.Onigao.Logic
{
    public class LevelServiceUnit : IReusableClass
    {
        private List<BaseServiceExecution> _preExecutions = new List<BaseServiceExecution>();
        private List<BaseServiceExecution> _executions = new List<BaseServiceExecution>();
        private List<BaseServiceExecution> _vetoExecutions = new List<BaseServiceExecution>();
        /// <summary>
        /// 是否触发过执行，用于判断是否是被再利用的pool对象，详情请见调用处
        /// </summary>
        private bool _executed = false;
        private LevelServiceUnitConfig _unitConfig;

        public int serviceId { get; private set; }
        public int index { get; private set; }
        public BaseLevelFunctionHost host { get; private set; }
        public ServiceBreakType breakType => _unitConfig.breakType;
        public int delay => _unitConfig.delay;
        public bool disabled { get; set; }

        public uint MaxStore => 100;

        public void Init(int serviceId, int index, LevelServiceUnitConfig unitConfig, BaseLevelFunctionHost host)
        {
            this.serviceId = serviceId;
            this.index = index;
            this._unitConfig = unitConfig;
            this.host = host;
            this.disabled = unitConfig.disabled;
            foreach (BaseServiceExecConfig execConfig in unitConfig.preExecution)
            {
                CreateExecution(serviceId, execConfig, host, _preExecutions);
            }
            foreach (BaseServiceExecConfig execConfig in unitConfig.execution)
            {
                CreateExecution(serviceId, execConfig, host, _executions);
            }
            foreach (BaseServiceExecConfig execConfig in unitConfig.vetoExecution)
            {
                CreateExecution(serviceId, execConfig, host, _vetoExecutions);
            }
        }

        private void CreateExecution(int serviceId, BaseServiceExecConfig execConfig, BaseLevelFunctionHost host, List<BaseServiceExecution> execList)
        {
            BaseServiceExecution execution = ServiceFactory.CreateExecution(execConfig.execType);
            if (execution != null)
            {
                execution.Initalize(execConfig, serviceId, host);
                execList.Add(execution);
            }
            else
            {
                LogicLog.LogError($"创建执行失败。execution type: {execConfig.execType}, entity mcid: {(host as LevelEntity)?.entityConfig.id}, service cid: {serviceId}");
            }
        }

        public bool CheckCondition(LevelPlayer player)
        {
            (bool isOK, int _) = ConditionLevelLogicUtil.Check(_unitConfig.conditionID, host?.region ?? player.region, player, host as LevelEntity);
            return isOK;
        }

        public int GetCanExecCount(bool isConditionOK)
        {
            return _preExecutions.Count + (isConditionOK ? _executions.Count : _vetoExecutions.Count);
        }

        public int Execute(LevelPlayer player, bool isConditionOK)
        {
            _executed = true;
            List<BaseServiceExecution> toExecutes = isConditionOK ? _executions : _vetoExecutions;
            int execCount = _preExecutions.Count + toExecutes.Count;
            //pre executions
            InnerExecutions(player, _preExecutions);
            //ok executions or failedExecutions
            InnerExecutions(player, toExecutes);
            return execCount;
        }

        private void InnerExecutions(LevelPlayer player, List<BaseServiceExecution> toExecutes)
        {
            List<BaseServiceExecution> tempExecList = ListPool<BaseServiceExecution>.Get();
            {
                tempExecList.AddRange(toExecutes);
                foreach (BaseServiceExecution execution in tempExecList)
                {
                    execution.Execute(host?.region ?? player.region, player);
                    //执行过程中，可能会销毁当前服务（如：替换服务），后续执行作废
                    //服务被销毁后，_executed会被重置为false
                    //不能通过如cfgData == null来判断服务是否在执行过程中被销毁，因为它在销毁后可能会从对象池中被取出，变成新的服务。
                    //但_executed不同，它只会在触发执行后改变，而新服务不可能在旧服务执行过程中触发执行
                    if (!_executed)
                    {
                        break;
                    }
                }
                ListPool<BaseServiceExecution>.Put(tempExecList);
            }
        }

        public void OnReset()
        {
            foreach (var exec in _preExecutions)
            {
                ClassPool.PutAutoType(exec);
            }
            _preExecutions.Clear();
            foreach (var exec in _executions)
            {
                ClassPool.PutAutoType(exec);
            }
            _executions.Clear();
            foreach (var exec in _vetoExecutions)
            {
                ClassPool.PutAutoType(exec);
            }
            _vetoExecutions.Clear();
            serviceId = 0;
            host = null;
            _unitConfig = null;
            _executed = false;
            disabled = false;
            index = 0;
        }
    }
}
